#include "task_group.h"
#include "login_connect_task.h"
#include "login_verify_task.h"
#include "login_gw_verify_task.h"
#include "login_authority_task.h"
#include <core/sharedata/login_data.h>
#include <algorithm>

#define FAIL_TRY_COUNT 3

namespace qb
{
    CTaskGroup::CTaskGroup(int nType)
        : m_nCurrentTask(-1)
        , m_nTrys(0)
		, m_pLoginConnectTask(NULL)
		, m_pLoginVerifyTask(NULL)
		, m_pGWConnectTask(NULL)
		, m_pLoginGwVerifyTask(NULL)
        , m_pLoginAuthorityTask(NULL)
    {

    }

    CTaskGroup::~CTaskGroup()
    {
        m_tasks.clear();
    }

    CTask* CTaskGroup::GetCurrentTask() const
    {
        if (m_nCurrentTask >= 0 && m_nCurrentTask < static_cast<int>(m_tasks.size()))
        {
            std::list<CTask*>::const_iterator it = m_tasks.begin();
            std::advance(it, m_nCurrentTask);
            return *it;
        }
        return NULL;
    }

    void CTaskGroup::Append(CTask* pTask)
    {
        if (pTask)
        {
            std::list<CTask*>::const_iterator it = std::find(m_tasks.begin(), m_tasks.end(), pTask);
            if (it == m_tasks.end())
            {
                m_tasks.push_back(pTask);
                pTask->SetObserver(this);
            }
        }        
    }

    bool CTaskGroup::IsAllTaskFinished()
    {
        int nCount = static_cast<int>(m_tasks.size());
        if (nCount <= 0)
        {
            return true;
        }
        return (m_nCurrentTask >= (nCount - 1));
    }

    bool CTaskGroup::OnNetData(char* pData, int nDataLen)
    {
		CTask* pTask = GetCurrentTask();
        QB_CHECK_RETURN_BOOL1(pTask);

		pTask->OnRecvNetData(pData, nDataLen);
        return true;
    }

    bool CTaskGroup::OnNetStatus(int32_t status)
    {
		CTask* pTask = GetCurrentTask();
        QB_CHECK_RETURN_BOOL1(pTask);

		pTask->OnRecvNetStatus(status);
        return true;
    }

    void CTaskGroup::StartNextTask()
    {
        if (++m_nCurrentTask >= 0 && m_nCurrentTask < static_cast<int>(m_tasks.size()))
        {
            std::list<CTask*>::iterator it = m_tasks.begin();
            std::advance(it, m_nCurrentTask);

            m_nTrys = 0;
            (*it)->Start();
        }
        else
        {        
            std::list<ITaskGroupObserver*>::iterator itObserver;
            for (itObserver = m_listObserver.begin(); itObserver != m_listObserver.end(); itObserver++)
            {
                if (*itObserver)
                {
                    (*itObserver)->OnAllTaskFinished();
                }
            }
        }
    }

    void CTaskGroup::OnTaskStep(qb::NetStatus status, short ret_code)
    {
        std::list<ITaskGroupObserver*>::iterator itObserver;
        for (itObserver = m_listObserver.begin(); itObserver != m_listObserver.end(); itObserver++)
        {
            if (*itObserver)
            {
                (*itObserver)->OnTaskStep(status, ret_code);
            }
        }
    }

    void CTaskGroup::OnTaskFinished(CTask* pTask)
    {
        StartNextTask();
    }

    void CTaskGroup::OnTaskFailed(CTask* /*pTask*/, qb::NetStatus status, short ret_code)
    {
        CTask* pTask = GetCurrentTask();
		QB_CHECK_RETURN_VOID1(pTask);

		if (pTask->IsConnectTask())
		{           
            std::list<ITaskGroupObserver*>::iterator itObserver;
            for (itObserver = m_listObserver.begin(); itObserver != m_listObserver.end(); itObserver++)
            {
                if (*itObserver)
                {
                    (*itObserver)->OnTaskGroupFailed(status, ret_code);
                }
            }
		}
		else
		{
            if (++m_nTrys > FAIL_TRY_COUNT)
            {
                std::list<ITaskGroupObserver*>::iterator itObserver;
                for (itObserver = m_listObserver.begin(); itObserver != m_listObserver.end(); itObserver++)
                {
                    if (*itObserver)
                    {
                        (*itObserver)->OnTaskGroupFailed(status, ret_code);
                    }
                }

                return;
            }

			pTask->Start();
		}
    }

	int32_t CTaskGroup::StartLoginSteps()
	{
		if (-1 != BuildLoginSteps())
		{
			return RunLoginSteps();
		}

		return -1;
	}

	int32_t CTaskGroup::BuildLoginSteps()
	{
		///////////////////////////////////////////////////////////////////////
		// 第一步: 连接登录服务器
		if (!m_pLoginConnectTask)
		{
            m_pLoginConnectTask = new CLoginConnectTask();
			QB_CHECK_RETURN_VALUE(m_pLoginConnectTask, -1);
			Append(m_pLoginConnectTask);
		}

		///////////////////////////////////////////////////////////////////////
		// 第二步: 登录服务器验证
		if (!m_pLoginVerifyTask)
		{
            m_pLoginVerifyTask = new CLoginVerifyTask();
			QB_CHECK_RETURN_VALUE(m_pLoginVerifyTask, -1);
			Append(m_pLoginVerifyTask);
		}

		///////////////////////////////////////////////////////////////////////
		// 第三步: 连接网关服务器
		if (!m_pGWConnectTask)
		{
            m_pGWConnectTask = new CLoginConnectTask();
			QB_CHECK_RETURN_VALUE(m_pGWConnectTask, -1);
			Append(m_pGWConnectTask);
		}

		///////////////////////////////////////////////////////////////////////
		// 第四步: 网关服务器验证
		if (!m_pLoginGwVerifyTask)
		{
            m_pLoginGwVerifyTask = new CLoginGwVerifyTask();
			QB_CHECK_RETURN_VALUE(m_pLoginGwVerifyTask, -1);
			Append(m_pLoginGwVerifyTask);
		}

		///////////////////////////////////////////////////////////////////////
		// 第五步: 请求用户权限
		if (!m_pLoginAuthorityTask)
		{
            m_pLoginAuthorityTask = new CLoginAuthorityTask();
			QB_CHECK_RETURN_VALUE(m_pLoginAuthorityTask, -1);
			Append(m_pLoginAuthorityTask);
		}

		return 0;
	}

	int32_t CTaskGroup::RunLoginSteps()
	{
		StartNextTask();
		return 0;
	}

	void CTaskGroup::StopLoginSteps()
	{
		m_nCurrentTask = -1;

		if (m_pLoginConnectTask)
		{
			m_pLoginConnectTask->Terminate();
		}

		if (m_pLoginVerifyTask)
		{
			m_pLoginVerifyTask->Terminate();
		}

		if (m_pGWConnectTask)
		{
			m_pGWConnectTask->Terminate();
		}

		if (m_pLoginGwVerifyTask)
		{
			m_pLoginGwVerifyTask->Terminate();
		}

        if (m_pLoginAuthorityTask)
        {
            m_pLoginAuthorityTask->Terminate();
        }
	}

	void CTaskGroup::DeleteTaskGroups()
	{
        m_tasks.clear();

		if (m_pLoginConnectTask)
		{
			delete m_pLoginConnectTask;
			m_pLoginConnectTask = NULL;
		}

		if (m_pLoginVerifyTask)
		{
			delete m_pLoginVerifyTask;
			m_pLoginVerifyTask = NULL;
		}

		if (m_pGWConnectTask)
		{
			delete m_pGWConnectTask;
			m_pGWConnectTask = NULL;
		}

		if (m_pLoginGwVerifyTask)
		{
			delete m_pLoginGwVerifyTask;
			m_pLoginGwVerifyTask = NULL;
		}

        if (m_pLoginAuthorityTask)
        {
            delete m_pLoginAuthorityTask;
            m_pLoginAuthorityTask = NULL;
        }
	}

}
